package com.school.empsys.service.impl;

import com.school.empsys.constants.AttendanceStatus;
import com.school.empsys.constants.LeavePermitStatus;
import com.school.empsys.constants.ResponseState;
import com.school.empsys.constants.Role;
import com.school.empsys.dto.EmpAppealDTO;
import com.school.empsys.dto.EmpAttendanceDTO;
import com.school.empsys.dto.EmpLeavePermitDTO;
import com.school.empsys.dto.ResponseInfo;
import com.school.empsys.mapper.EmpAppealMapper;
import com.school.empsys.mapper.EmpAttendanceMapper;
import com.school.empsys.mapper.EmpLeavePermitMapper;
import com.school.empsys.mapper.UserMapper;
import com.school.empsys.model.EmpAppeal;
import com.school.empsys.model.EmpAttendance;
import com.school.empsys.model.EmpLeavePermit;
import com.school.empsys.model.User;
import com.school.empsys.service.EmpAttendanceService;
import com.school.empsys.utils.DateUtils;
import com.school.empsys.utils.UserUtil;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class EmpAttendanceServiceImpl implements EmpAttendanceService {

    @Autowired
    EmpAttendanceMapper empAttendanceMapper;

    @Value("${punchTimeAtWork}")
    String punchTimeAtWork;

    @Value("${punchTimeAfterWork}")
    String punchTimeAfterWork;

    @Autowired
    UserMapper userMapper;

    @Autowired
    EmpLeavePermitMapper empLeavePermitMapper;

    @Override
    public int count(Map<String, Object> params) {
        return empAttendanceMapper.count(params);
    }

    @Override
    public List<EmpAttendance> list(Map<String, Object> params, Integer offset, Integer limit) {
        return empAttendanceMapper.list(params, offset, limit);
    }

    @Override
    public void save(EmpAttendance attendance) {
        empAttendanceMapper.insert(attendance);
    }

    @Override
    public EmpAttendance findOne(Integer id) {
        return empAttendanceMapper.selectByPrimaryKey(id);
    }

    @Override
    public ResponseInfo punchIn() {
        ResponseInfo responseInfo = this.checkPunch("punchIn");
        if (ResponseState.FAILURE.getCode().equals(responseInfo.getCode())) {
            return responseInfo;
        }
        EmpAttendance attendance = new EmpAttendance();
        Date now = new Date();
        Date dateWork = DateUtils.date2DateTime(now, punchTimeAtWork);
        attendance.setStatus(now.after(dateWork) ? AttendanceStatus.LATE.getName() : AttendanceStatus.NORMAL.getName());
        attendance.setUserId(UserUtil.getCurrentUser().getId().intValue());
        attendance.setDate(now);
        attendance.setCreateTime(now);
        attendance.setUpdateTime(now);
        attendance.setPunchTimeAtWork(now);
        int id = empAttendanceMapper.insert(attendance);

        attendance.setId(id);
        attendance.setUser(UserUtil.getCurrentUser());
        return ResponseInfo.SUCCESS.message("打卡成功");
    }

    @Override
    public ResponseInfo punchOut() {
        ResponseInfo responseInfo = this.checkPunch("punchOut");
        if (ResponseState.FAILURE.getCode().equals(responseInfo.getCode())) {
            return responseInfo;
        }
        Date now = new Date();
        List<EmpAttendance> list = this.selectUserDateAttendance(now, UserUtil.getCurrentUser());
        EmpAttendance attendance = list.get(0);

        Date dateWork = DateUtils.date2DateTime(now, punchTimeAtWork);
        Date endWork = DateUtils.date2DateTime(now, punchTimeAfterWork);
        //早退打卡
        if (now.after(dateWork) && now.before(endWork)) {
            if (attendance.getPunchTimeAtWork().after(dateWork)) {
                //迟到又早退打卡，当做旷工
                attendance.setStatus(AttendanceStatus.ABSENTEEISM.getName());
            } else {
                attendance.setStatus(AttendanceStatus.LEAVE_EARLY.getName());
            }
        }
        attendance.setPunchTimeAfterWork(new Date());
        attendance.setUpdateTime(new Date());
        empAttendanceMapper.updateByPrimaryKeySelective(attendance);
        return ResponseInfo.SUCCESS.message("下班打卡成功");
    }

    @Override
    public ResponseInfo checkPunch(String type) {
        Date now = new Date();
        Date dateWork = DateUtils.date2DateTime(now, punchTimeAtWork);
        Date endWork = DateUtils.date2DateTime(now, punchTimeAfterWork);
        List<EmpAttendance> list = this.selectUserDateAttendance(now, UserUtil.getCurrentUser());
        if ("punchIn".equals(type)) {
            //1.上班打卡检测
            //已有打卡记录
            if (!CollectionUtils.isEmpty(list)) {
                return ResponseInfo.FAILURE.message("已打过卡，请勿重新打卡");
            }
            //当前时间在下班后
            if (now.after(endWork)) {
                return ResponseInfo.FAILURE.message("不是上班打卡时间");
            }
            //当前时间在上班时间内
            if (now.after(dateWork) && now.before(endWork)) {
                return ResponseInfo.CONFIRM.message("已迟到，确定迟到打卡？");
            }
        } else if ("punchOut".equals(type)) {
            //2.下班打卡检测
            //本日打卡记录为空
            if (CollectionUtils.isEmpty(list)) {
                return ResponseInfo.FAILURE.message("请先打上班卡");
            }
            EmpAttendance empAttendance = list.get(0);
            //本日上班打卡时间为空
            if (empAttendance.getPunchTimeAtWork() == null) {
                return ResponseInfo.FAILURE.message("请先打上班卡");
            }
            //当前时间在上班时间内
            if (now.after(dateWork) && now.before(endWork)) {
                return ResponseInfo.CONFIRM.message("还未到下班时间，确定早退打卡？");
            }
            //本日已打下班卡
            if (empAttendance.getPunchTimeAfterWork() != null) {
                return ResponseInfo.FAILURE.message("已打过卡，请勿重新打卡");
            }
        } else {
            //3.检测类型不匹配
            return ResponseInfo.FAILURE.message("参数错误");
        }
        return ResponseInfo.SUCCESS;
    }

    @Override
    public void dailyAttendance() {
        Date now = new Date();
        Date dateWork = DateUtils.date2DateTime(now, punchTimeAtWork);
        Date endWork = DateUtils.date2DateTime(now, punchTimeAfterWork);
        List<User> users = userMapper.listEmps();
        if (!CollectionUtils.isEmpty(users)) {
            for (User user : users) {
                List<EmpAttendance> empAttendances = this.selectUserDateAttendance(now, user);
                //1.没有当日打卡记录
                if (CollectionUtils.isEmpty(empAttendances)) {
                    //1.1查询是否有请假申请：没有请假申请或请假申请审核不存在通过的视为旷工，生成旷工考勤记录；有请假申请且审核为通过的生成请假考勤记录
                    EmpLeavePermitDTO param = new EmpLeavePermitDTO();
                    param.setLeaveDate(dateWork);
                    List<EmpLeavePermit> empLeavePermitList = empLeavePermitMapper.selectByEmpLeavePermit(param);
                    if (CollectionUtils.isEmpty(empLeavePermitList)) {
                        save(getEmpAttendance(user, AttendanceStatus.ABSENTEEISM.getName()));
                    } else {
                        List<String> statusList = empLeavePermitList.stream().map(EmpLeavePermit::getStatus).collect(Collectors.toList());
                        if (!statusList.contains(LeavePermitStatus.PASS.getName())) {
                            save(getEmpAttendance(user, AttendanceStatus.ABSENTEEISM.getName()));
                        } else if (statusList.contains(LeavePermitStatus.PASS.getName())) {
                            save(getEmpAttendance(user, AttendanceStatus.ASK_FOR_LEAVE.getName()));
                        }
                    }
                } else {
                    EmpAttendance empAttendance = empAttendances.get(0);
                    //2.有打卡记录，根据上班打卡和下班打卡时间得到打卡状态
                    String status = null;
                    if (empAttendance.getPunchTimeAtWork() == null && empAttendance.getPunchTimeAfterWork() == null) {
                        status = AttendanceStatus.ABSENTEEISM.getName();
                    } else if (empAttendance.getPunchTimeAtWork() != null && empAttendance.getPunchTimeAfterWork() == null) {
                        status = AttendanceStatus.LEAVE_EARLY.getName();
                    }
                    if (status != null) {
                        empAttendance.setStatus(status);
                        empAttendance.setUpdateTime(new Date());
                        empAttendanceMapper.updateByPrimaryKeySelective(empAttendance);
                    }
                }
            }
        }
    }


    public List<EmpAttendance> selectUserDateAttendance(Date date, User currentUser) {
        Integer userId = currentUser.getId().intValue();
        Date day = DateUtils.date2PatternDate(date, DateUtils.DateFormatPattern.PATTERN_1);

        EmpAttendanceDTO param = new EmpAttendanceDTO();
        param.setUserId(userId);
        param.setDate(day);
        return empAttendanceMapper.selectByEmpAttendanceDTO(param);
    }


    public EmpAttendance getEmpAttendance(User user, String status) {
        Date now = new Date();
        EmpAttendance empAttendance = new EmpAttendance();
        empAttendance.setDate(now);
        empAttendance.setCreateTime(now);
        empAttendance.setUpdateTime(now);
        /*empAttendance.setPunchTimeAtWork(now);
        empAttendance.setPunchTimeAfterWork(now);*/
        empAttendance.setUserId(user.getId().intValue());
        empAttendance.setStatus(status);
        return empAttendance;
    }

}
